package example.aop;

import example.constant.ResponseEnum;
import example.exception.BizException;
import example.param.Param;
import example.result.Result;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 * Created by zhouzixiong on 2017/4/18.
 */
@Aspect
@Component
public class ExpResponseAspect {

    private static final Logger LOGGER = LoggerFactory.getLogger(ExpResponseAspect.class);

    @Pointcut("@annotation(example.aop.NewExpResponse)")
    private void pointCutMethod() {
    }

    @Around("pointCutMethod()")
    public Object proceed(ProceedingJoinPoint proceedingJoinPoint) {
        long begin = System.currentTimeMillis();
        Object[] args = proceedingJoinPoint.getArgs();
        try {
            if (null != args && args.length > 0) {
                for (Object arg : args) {
                    if (arg instanceof Param) {
                        ((Param) arg).check();
                    }
                }
            }
        }catch (BizException e){
            if(LOGGER.isDebugEnabled()){
                LOGGER.debug("Param check false.", e);
            }
            return new Result(e.getCode(), e.getMessage());
        }
        Result result = new Result(ResponseEnum.SUCCESS);
        try{
            Object obj = proceedingJoinPoint.proceed();
            if(null != obj && obj instanceof Result){
                return obj;
            }
            result = new Result(obj);
        }catch (Throwable t){
            LOGGER.error("Fail to return result.", t);
            if( t instanceof BizException){
                return new Result(((BizException)t).getCode(), ((BizException)t).getMessage());
            }
            return new Result(ResponseEnum.SYSTEM_ERR.getCode(), t.getMessage());
        }finally {
            long end = System.currentTimeMillis();
            if(LOGGER.isDebugEnabled()){
                LOGGER.debug("{}, cost time :{}ms.", proceedingJoinPoint.getSignature().getDeclaringTypeName() + "_" + proceedingJoinPoint.getSignature().getName(), (end - begin));
            }
        }
        return result;
    }
}
